home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / FunctionObject.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  21.0 KB  |  751 lines  |  [TEXT/KAHL]

  1. /* FunctionObject.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "FunctionObject.h"
  31. #include "Memory.h"
  32. #include "DataMunging.h"
  33. #include "CodeCenter.h"
  34. #include "Numbers.h"
  35. #include "Alert.h"
  36. #include "Array.h"
  37. #include "PcodeDisassembly.h"
  38. #include "FunctionWindow.h"
  39. #include "FunctionList.h"
  40. #include "CompilerRoot.h"
  41. #include "FunctionCode.h"
  42. #include "BufferedFileInput.h"
  43. #include "BufferedFileOutput.h"
  44.  
  45.  
  46. struct FunctionObjectRec
  47.     {
  48.         MyBoolean                                Modified;
  49.         char*                                        Source;
  50.         char*                                        Name;
  51.  
  52.         MyBoolean                                Built;
  53.         MyBoolean                                NeedsToBeRebuilt;
  54.         CodeCenterRec*                    CodeCenter;
  55.  
  56.         FunctionWindowRec*            Window;
  57.         struct MainWindowRec*        MainWindow;
  58.         FunctionListRec*                FuncList;
  59.  
  60.         short                                        SavedWindowXLoc;
  61.         short                                        SavedWindowYLoc;
  62.         short                                        SavedWindowWidth;
  63.         short                                        SavedWindowHeight;
  64.     };
  65.  
  66.  
  67. FunctionObjectRec*    NewFunctionObject(struct CodeCenterRec* CodeCenter,
  68.                                             struct MainWindowRec* MainWindow,
  69.                                             struct FunctionListRec* FuncList)
  70.     {
  71.         FunctionObjectRec*    FuncObj;
  72.  
  73.         CheckPtrExistence(CodeCenter);
  74.         FuncObj = (FunctionObjectRec*)AllocPtrCanFail(sizeof(FunctionObjectRec),
  75.             "FunctionObjectRec");
  76.         if (FuncObj == NIL)
  77.             {
  78.              FailurePoint1:
  79.                 return NIL;
  80.             }
  81.         FuncObj->Source = AllocPtrCanFail(0,"FuncModuleSourceCode");
  82.         if (FuncObj->Source == NIL)
  83.             {
  84.              FailurePoint2:
  85.                 ReleasePtr((char*)FuncObj);
  86.                 goto FailurePoint1;
  87.             }
  88.         FuncObj->Name = StringToBlockCopy("untitled");
  89.         if (FuncObj->Name == NIL)
  90.             {
  91.              FailurePoint3:
  92.                 ReleasePtr(FuncObj->Source);
  93.                 goto FailurePoint2;
  94.             }
  95.         SetTag(FuncObj->Name,"FuncModuleName");
  96.         FuncObj->Modified = False;
  97.         FuncObj->NeedsToBeRebuilt = True;
  98.         FuncObj->Built = False;
  99.         FuncObj->CodeCenter = CodeCenter;
  100.         FuncObj->Window = NIL;
  101.         FuncObj->MainWindow = MainWindow;
  102.         FuncObj->FuncList = FuncList;
  103.         FuncObj->SavedWindowXLoc = 0;
  104.         FuncObj->SavedWindowYLoc = 0;
  105.         FuncObj->SavedWindowWidth = 0;
  106.         FuncObj->SavedWindowHeight = 0;
  107.         return FuncObj;
  108.     }
  109.  
  110.  
  111. /* get rid of the function object */
  112. void                                DisposeFunctionObject(FunctionObjectRec* FuncObj)
  113.     {
  114.         CheckPtrExistence(FuncObj);
  115.         /* don't leave our object code laying around after we're dead */
  116.         FunctionObjectUnbuild(FuncObj);
  117.         /* close the window if it is open */
  118.         if (FuncObj->Window != NIL)
  119.             {
  120.                 DisposeFunctionWindow(FuncObj->Window);
  121.                 ERROR(FuncObj->Window != NIL,PRERR(AllowResume,
  122.                     "DisposeFunctionObject:  window thing not NIL after DisposeFunctionWindow"));
  123.             }
  124.         /* dispose of used memory */
  125.         ReleasePtr(FuncObj->Source);
  126.         ReleasePtr(FuncObj->Name);
  127.         ReleasePtr((char*)FuncObj);
  128.     }
  129.  
  130.  
  131. /* inquire whether the function has been modified */
  132. MyBoolean                        HasFunctionObjectBeenModified(FunctionObjectRec* FuncObj)
  133.     {
  134.         MyBoolean                    Result;
  135.  
  136.         CheckPtrExistence(FuncObj);
  137.         Result = FuncObj->Modified;
  138.         if (FuncObj->Window != NIL)
  139.             {
  140.                 Result = Result || HasFunctionWindowBeenModified(FuncObj->Window);
  141.             }
  142.         return Result;
  143.     }
  144.  
  145.  
  146. /* build the function module code.  returns True if successful. */
  147. MyBoolean                        FunctionObjectBuild(FunctionObjectRec* FuncObj)
  148.     {
  149.         char*                            Data;
  150.         long                            ErrorLine;
  151.         CompileErrors            Error;
  152.         char*                            ErrorString;
  153.         MyBoolean                    SuccessFlag;
  154.  
  155.         CheckPtrExistence(FuncObj);
  156.  
  157.         /* make sure our old stuff isn't hanging around */
  158.         FunctionObjectUnbuild(FuncObj);
  159.  
  160.         /* obtain the source text to be compiled */
  161.         Data = FunctionObjectGetSourceCopy(FuncObj);
  162.         if (Data == NIL)
  163.             {
  164.                 AlertHalt("There is not enough memory available to "
  165.                     "build the function module.",NIL);
  166.                 return False;
  167.             }
  168.  
  169.         /* compile the module */
  170.         Error = CompileModule(&ErrorLine,Data,FuncObj/*signature*/,FuncObj->CodeCenter);
  171.  
  172.         /* dispose of the copy of the source text */
  173.         ReleasePtr(Data);
  174.  
  175.         /* if no errors occurred, then everything is fine */
  176.         if (Error == eCompileNoError)
  177.             {
  178.                 /* indicate that we are now successfully built & return */
  179.                 FuncObj->Built = True;
  180.                 FuncObj->NeedsToBeRebuilt = False;
  181.                 return True;
  182.             }
  183.  
  184.         /* since an error occurred, open the editor window so that we can show */
  185.         /* where it occurred */
  186.         if (!FunctionObjectOpenWindow(FuncObj))
  187.             {
  188.              FailureMessagePoint:
  189.                 AlertHalt("A compile error occurred but there is not enough memory available to "
  190.                     "display the error message.",NIL);
  191.                 return False;
  192.             }
  193.  
  194.         /* now, hilite the error line. we subtract one because error lines are */
  195.         /* returned starting at 1, but our line numbers start at 0. */
  196.         FunctionWindowHiliteLine(FuncObj->Window,ErrorLine - 1);
  197.  
  198.         /* figure out what the error string is */
  199.         SuccessFlag = False;
  200.         ErrorString = StringFromRaw(GetCompileErrorString(Error));
  201.         if (ErrorString != NIL)
  202.             {
  203.                 char*                    NumberString;
  204.  
  205.                 NumberString = IntegerToString(ErrorLine);
  206.                 if (NumberString != NIL)
  207.                     {
  208.                         char*                    Key;
  209.  
  210.                         Key = StringToBlockCopy("_");
  211.                         if (Key != NIL)
  212.                             {
  213.                                 char*                    BaseMessage;
  214.  
  215.                                 BaseMessage = StringFromRaw("Error on line _:  _");
  216.                                 if (BaseMessage != NIL)
  217.                                     {
  218.                                         char*                    FixedMessage;
  219.  
  220.                                         FixedMessage = ReplaceBlockCopy(BaseMessage,Key,NumberString);
  221.                                         if (FixedMessage != NIL)
  222.                                             {
  223.                                                 AlertHalt(FixedMessage,ErrorString);
  224.                                                 ReleasePtr(FixedMessage);
  225.                                                 SuccessFlag = True;
  226.                                             }
  227.                                         ReleasePtr(BaseMessage);
  228.                                     }
  229.                                 ReleasePtr(Key);
  230.                             }
  231.                         ReleasePtr(NumberString);
  232.                     }
  233.                 ReleasePtr(ErrorString);
  234.             }
  235.         if (!SuccessFlag)
  236.             {
  237.                 goto FailureMessagePoint;
  238.             }
  239.         return False;
  240.     }
  241.  
  242.  
  243. /* unconditionally unbuild the functions */
  244. void                                FunctionObjectUnbuild(FunctionObjectRec* FuncObj)
  245.     {
  246.         CheckPtrExistence(FuncObj);
  247.         if (FuncObj->Built)
  248.             {
  249.                 FlushModulesCompiledFunctions(FuncObj->CodeCenter,FuncObj/*signature*/);
  250.                 FuncObj->Built = False;
  251.             }
  252.     }
  253.  
  254.  
  255. /* build the functions if necessary.  return True if successful. */
  256. MyBoolean                        FunctionObjectMakeUpToDate(FunctionObjectRec* FuncObj)
  257.     {
  258.         CheckPtrExistence(FuncObj);
  259.         if (!FuncObj->Built || FuncObj->NeedsToBeRebuilt || (FuncObj->Window != NIL))
  260.             {
  261.                 return FunctionObjectBuild(FuncObj);
  262.             }
  263.          else
  264.             {
  265.                 return True;
  266.             }
  267.     }
  268.  
  269.  
  270. /* return a text block containing a disassembly of the function module */
  271. char*                                FunctionObjectDisassemble(FunctionObjectRec* FuncObj)
  272.     {
  273.         ArrayRec*                    ListOfFunctions;
  274.         long                            Scan;
  275.         char*                            BigDaddie;
  276.         long                            Limit;
  277.  
  278.         CheckPtrExistence(FuncObj);
  279.  
  280.         /* make sure there is something to disassemble */
  281.         if (!FunctionObjectMakeUpToDate(FuncObj))
  282.             {
  283.                 return NIL;
  284.             }
  285.  
  286.         /* allocate the initial text buffer */
  287.         BigDaddie = AllocPtrCanFail(0,"BigDaddieDisassembly");
  288.         if (BigDaddie == NIL)
  289.             {
  290.              FailurePoint0:
  291.                 return NIL;
  292.             }
  293.  
  294.         /* get a list of functions that need to be disassembled */
  295.         ListOfFunctions = GetListOfFunctionsForModule(FuncObj->CodeCenter,
  296.             FuncObj/*signature*/);
  297.  
  298.         if (ListOfFunctions == NIL)
  299.             {
  300.              FailurePoint1:
  301.                 ReleasePtr(BigDaddie);
  302.                 goto FailurePoint0;
  303.             }
  304.  
  305.         /* for each function, disassemble it */
  306.         Limit = ArrayGetLength(ListOfFunctions);
  307.         for (Scan = 0; Scan < Limit; Scan += 1)
  308.             {
  309.                 FuncCodeRec*            TheFunction;
  310.                 char*                            FuncName;
  311.                 PcodeRec*                    FuncCode;
  312.                 char*                            TextTemp;
  313.                 long                            OldSize;
  314.                 char*                            DisDump;
  315.  
  316.                 TheFunction = (FuncCodeRec*)ArrayGetElement(ListOfFunctions,Scan);
  317.                 /* get the actual name (not a copy), null terminated */
  318.                 FuncName = GetFunctionName(TheFunction);
  319.                 /* get the code to be disassembled */
  320.                 FuncCode = GetFunctionPcode(TheFunction);
  321.                 /* resize the array to make space for the names */
  322.                 OldSize = PtrSize(BigDaddie);
  323.                 TextTemp = ResizePtr((char*)BigDaddie,OldSize + 2 + PtrSize(FuncName) + 1);
  324.                 if (TextTemp == NIL)
  325.                     {
  326.                      FailurePoint2:
  327.                         DisposeArray(ListOfFunctions);
  328.                         goto FailurePoint1;
  329.                     }
  330.                 BigDaddie = TextTemp;
  331.                 /* copy over name of function */
  332.                 PRNGCHK(BigDaddie,&(BigDaddie[OldSize + 0]),2);
  333.                 CopyData("\x0a\x0a",&(BigDaddie[OldSize + 0]),2);
  334.                 PRNGCHK(BigDaddie,&(BigDaddie[OldSize + 2]),PtrSize(FuncName));
  335.                 CopyData(FuncName,&(BigDaddie[OldSize + 2]),PtrSize(FuncName));
  336.                 PRNGCHK(BigDaddie,&(BigDaddie[OldSize + 2 + PtrSize(FuncName)]),1);
  337.                 CopyData("\x0a",&(BigDaddie[OldSize + 2 + PtrSize(FuncName)]),1);
  338.                 /* obtain the text of the disassembly for the specified function */
  339.                 DisDump = DisassemblePcode(FuncCode,'\x0a');
  340.                 if (DisDump == NIL)
  341.                     {
  342.                         goto FailurePoint2;
  343.                     }
  344.                 /* resize the big text block to make room for the disassembly */
  345.                 OldSize = PtrSize(BigDaddie);
  346.                 TextTemp = ResizePtr((char*)BigDaddie,OldSize + PtrSize(DisDump));
  347.                 if (TextTemp == NIL)
  348.                     {
  349.                         ReleasePtr(DisDump);
  350.                         goto FailurePoint2;
  351.                     }
  352.                 BigDaddie = TextTemp;
  353.                 /* copy the disassembly text over */
  354.                 PRNGCHK(BigDaddie,&(BigDaddie[OldSize]),PtrSize(DisDump));
  355.                 CopyData(DisDump,&(BigDaddie[OldSize]),PtrSize(DisDump));
  356.                 /* dispose of the old disassembly text */
  357.                 ReleasePtr(DisDump);
  358.             }
  359.  
  360.         /* get rid of the list of functions */
  361.         DisposeArray(ListOfFunctions);
  362.  
  363.         /* return the full disassembly to the caller */
  364.         return BigDaddie;
  365.     }
  366.  
  367.  
  368. /* get a copy of the name of this function module, no null termination */
  369. char*                                FunctionObjectGetNameCopy(FunctionObjectRec* FuncObj)
  370.     {
  371.         char*                            NameCopy;
  372.  
  373.         CheckPtrExistence(FuncObj);
  374.         if (FuncObj->Window != NIL)
  375.             {
  376.                 NameCopy = FunctionWindowGetNameCopy(FuncObj->Window);
  377.             }
  378.          else
  379.             {
  380.                 NameCopy = CopyPtr(FuncObj->Name);
  381.             }
  382.         if (NameCopy != NIL)
  383.             {
  384.                 SetTag(NameCopy,"FuncObjNameCopy");
  385.             }
  386.         return NameCopy;
  387.     }
  388.  
  389.  
  390. /* open the window for this function */
  391. MyBoolean                        FunctionObjectOpenWindow(FunctionObjectRec* FuncObj)
  392.     {
  393.         CheckPtrExistence(FuncObj);
  394.         if (FuncObj->Window != NIL)
  395.             {
  396.                 FunctionWindowBringToTop(FuncObj->Window);
  397.             }
  398.          else
  399.             {
  400.                 FuncObj->Window = NewFunctionWindow(FuncObj->MainWindow,FuncObj,
  401.                     FuncObj->FuncList,FuncObj->SavedWindowXLoc,FuncObj->SavedWindowYLoc,
  402.                     FuncObj->SavedWindowWidth,FuncObj->SavedWindowHeight);
  403.             }
  404.         return (FuncObj->Window != NIL);
  405.     }
  406.  
  407.  
  408. /* get the text for this function */
  409. char*                                FunctionObjectGetSourceCopy(FunctionObjectRec* FuncObj)
  410.     {
  411.         char*                            DataCopy;
  412.  
  413.         CheckPtrExistence(FuncObj);
  414.         if (FuncObj->Window != NIL)
  415.             {
  416.                 DataCopy = FunctionWindowGetSourceCopy(FuncObj->Window);
  417.             }
  418.          else
  419.             {
  420.                 DataCopy = CopyPtr(FuncObj->Source);
  421.             }
  422.         if (DataCopy != NIL)
  423.             {
  424.                 SetTag(DataCopy,"FuncObjSourceCopy");
  425.             }
  426.         return DataCopy;
  427.     }
  428.  
  429.  
  430. /* install new data in the object.  this is used when the editor window closes, */
  431. /* to put the new data into this object.  the object becomes the owner of Data, */
  432. /* so the caller should not release it. */
  433. void                                FunctionObjectNewSource(FunctionObjectRec* FuncObj, char* Data)
  434.     {
  435.         CheckPtrExistence(FuncObj);
  436.         CheckPtrExistence(Data);
  437.         SetTag(Data,"FuncObjSourceImported");
  438.         ReleasePtr(FuncObj->Source);
  439.         FuncObj->Source = Data;
  440.         FuncObj->Modified = True;
  441.         FuncObj->NeedsToBeRebuilt = True;
  442.     }
  443.  
  444.  
  445. /* give function module a new name.  the object becomes the owner of Name, so */
  446. /* the caller should not release it. */
  447. void                                FunctionObjectNewName(FunctionObjectRec* FuncObj, char* Name)
  448.     {
  449.         CheckPtrExistence(FuncObj);
  450.         CheckPtrExistence(Name);
  451.         SetTag(Name,"FuncObjNameImported");
  452.         ReleasePtr(FuncObj->Name);
  453.         FuncObj->Name = Name;
  454.         FuncObj->Modified = True;
  455.         FuncObj->NeedsToBeRebuilt = True;
  456.         FunctionListFunctionNameChanged(FuncObj->FuncList,FuncObj);
  457.     }
  458.  
  459.  
  460. /* this is called when the window is closing.  it notifies the object.  the */
  461. /* object should not take any action. */
  462. void                                FunctionObjectClosingWindowNotify(FunctionObjectRec* FuncObj,
  463.                                             short NewWindowX, short NewWindowY, short NewWindowWidth,
  464.                                             short NewWindowHeight)
  465.     {
  466.         CheckPtrExistence(FuncObj);
  467.         ERROR(FuncObj->Window == NIL,PRERR(ForceAbort,
  468.             "FunctionObjectClosingWindowNotify:  window isn't open"));
  469.         FuncObj->Window = NIL;
  470.         FuncObj->SavedWindowXLoc = NewWindowX;
  471.         FuncObj->SavedWindowYLoc = NewWindowY;
  472.         FuncObj->SavedWindowWidth = NewWindowWidth;
  473.         FuncObj->SavedWindowHeight = NewWindowHeight;
  474.     }
  475.  
  476.  
  477. /* the document's name has changed, so we need to update the window */
  478. void                                FunctionObjectGlobalNameChange(FunctionObjectRec* FuncObj,
  479.                                             char* NewFilename)
  480.     {
  481.         CheckPtrExistence(FuncObj);
  482.         if (FuncObj->Window != NIL)
  483.             {
  484.                 FunctionWindowGlobalNameChange(FuncObj->Window,NewFilename);
  485.             }
  486.     }
  487.  
  488.  
  489. /* Function Object Subblock Structure: */
  490. /*   1-byte function object version number */
  491. /*       should be 1 */
  492. /*   2-byte little endian window x location (origin at top-left of screen) */
  493. /*   2-byte little endian window y location */
  494. /*   2-byte little endian window width */
  495. /*   2-byte little endian window height */
  496. /*   4-byte little endian object name length (positive 2s complement) */
  497. /*   n-byte name data (line feed = 0x0a) */
  498. /*   4-byte little endian function source text length (positive 2s complement) */
  499. /*   n-byte function source text data (line feed = 0x0a) */
  500.  
  501.  
  502. /* create a new object initialized with data read in from a file. */
  503. FileLoadingErrors        FunctionObjectNewFromFile(FunctionObjectRec** ObjectOut,
  504.                                             struct BufferedInputRec* Input, struct CodeCenterRec* CodeCenter,
  505.                                             struct MainWindowRec* MainWindow,
  506.                                             struct FunctionListRec* FuncList)
  507.     {
  508.         FunctionObjectRec*    FuncObj;
  509.         signed short                SignedShort;
  510.         FileLoadingErrors        Error;
  511.         signed long                    BlockLength;
  512.         unsigned char                FormatVersionNumber;
  513.  
  514.         CheckPtrExistence(Input);
  515.         CheckPtrExistence(CodeCenter);
  516.         CheckPtrExistence(MainWindow);
  517.         CheckPtrExistence(FuncList);
  518.  
  519.         /* create a new object thang */
  520.         FuncObj = (FunctionObjectRec*)AllocPtrCanFail(sizeof(FunctionObjectRec),
  521.             "FunctionObjectRec");
  522.         if (FuncObj == NIL)
  523.             {
  524.                 Error = eFileLoadOutOfMemory;
  525.              FailurePoint1:
  526.                 return Error;
  527.             }
  528.  
  529.         /*   1-byte function object version number */
  530.         /*       should be 1 */
  531.         if (!ReadBufferedUnsignedChar(Input,&FormatVersionNumber))
  532.             {
  533.                 Error = eFileLoadDiskError;
  534.              FailurePoint2:
  535.                 ReleasePtr((char*)FuncObj);
  536.                 goto FailurePoint1;
  537.             }
  538.         if (FormatVersionNumber != 1)
  539.             {
  540.                 Error = eFileLoadBadFormat;
  541.              FailurePoint3:
  542.                 goto FailurePoint2;
  543.             }
  544.  
  545.         /*   2-byte little endian window x location (origin at top-left of screen) */
  546.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  547.             {
  548.                 Error = eFileLoadDiskError;
  549.              FailurePoint4:
  550.                 goto FailurePoint3;
  551.             }
  552.         FuncObj->SavedWindowXLoc = SignedShort;
  553.  
  554.         /*   2-byte little endian window y location */
  555.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  556.             {
  557.                 Error = eFileLoadDiskError;
  558.              FailurePoint5:
  559.                 goto FailurePoint4;
  560.             }
  561.         FuncObj->SavedWindowYLoc = SignedShort;
  562.  
  563.         /*   2-byte little endian window width */
  564.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  565.             {
  566.                 Error = eFileLoadDiskError;
  567.              FailurePoint6:
  568.                 goto FailurePoint5;
  569.             }
  570.         FuncObj->SavedWindowWidth = SignedShort;
  571.  
  572.         /*   2-byte little endian window height */
  573.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  574.             {
  575.                 Error = eFileLoadDiskError;
  576.              FailurePoint7:
  577.                 goto FailurePoint6;
  578.             }
  579.         FuncObj->SavedWindowHeight = SignedShort;
  580.  
  581.         /*   4-byte little endian object name length */
  582.         if (!ReadBufferedSignedLongLittleEndian(Input,&BlockLength))
  583.             {
  584.                 Error = eFileLoadDiskError;
  585.              FailurePoint8:
  586.                 goto FailurePoint7;
  587.             }
  588.         if (BlockLength < 0)
  589.             {
  590.                 Error = eFileLoadBadFormat;
  591.              FailurePoint9:
  592.                 goto FailurePoint8;
  593.             }
  594.  
  595.         /*   n-byte name data (line feed = 0x0a) */
  596.         FuncObj->Name = AllocPtrCanFail(BlockLength,"FunctionObjectRec: name");
  597.         if (FuncObj->Name == NIL)
  598.             {
  599.                 Error = eFileLoadOutOfMemory;
  600.              FailurePoint10:
  601.                 goto FailurePoint9;
  602.             }
  603.         if (!ReadBufferedInput(Input,BlockLength,FuncObj->Name))
  604.             {
  605.                 Error = eFileLoadDiskError;
  606.              FailurePoint11:
  607.                 ReleasePtr(FuncObj->Name);
  608.                 goto FailurePoint10;
  609.             }
  610.  
  611.         /*   4-byte little endian function source text length */
  612.         if (!ReadBufferedSignedLongLittleEndian(Input,&BlockLength))
  613.             {
  614.                 Error = eFileLoadDiskError;
  615.              FailurePoint12:
  616.                 goto FailurePoint11;
  617.             }
  618.         if (BlockLength < 0)
  619.             {
  620.                 Error = eFileLoadBadFormat;
  621.              FailurePoint13:
  622.                 goto FailurePoint12;
  623.             }
  624.  
  625.         /*   n-byte function source text data (line feed = 0x0a) */
  626.         FuncObj->Source = AllocPtrCanFail(BlockLength,"FunctionObjectRec: source");
  627.         if (FuncObj->Source == NIL)
  628.             {
  629.                 Error = eFileLoadOutOfMemory;
  630.              FailurePoint14:
  631.                 goto FailurePoint13;
  632.             }
  633.         if (!ReadBufferedInput(Input,BlockLength,FuncObj->Source))
  634.             {
  635.                 Error = eFileLoadDiskError;
  636.              FailurePoint15:
  637.                 ReleasePtr(FuncObj->Source);
  638.                 goto FailurePoint14;
  639.             }
  640.  
  641.         /* now fill in the other stuff */
  642.         FuncObj->Modified = False;
  643.         FuncObj->Built = False;
  644.         FuncObj->NeedsToBeRebuilt = True;
  645.         FuncObj->CodeCenter = CodeCenter;
  646.         FuncObj->Window = NIL;
  647.         FuncObj->MainWindow = MainWindow;
  648.         FuncObj->FuncList = FuncList;
  649.  
  650.         *ObjectOut = FuncObj;
  651.         return eFileLoadNoError;
  652.     }
  653.  
  654.  
  655. /* write the data in an object out to disk */
  656. FileLoadingErrors        FunctionObjectWriteOutData(FunctionObjectRec* FuncObj,
  657.                                             struct BufferedOutputRec* Output)
  658.     {
  659.         char*                            StringTemp;
  660.  
  661.         CheckPtrExistence(FuncObj);
  662.         CheckPtrExistence(Output);
  663.  
  664.         /*   1-byte function object version number */
  665.         /*       should be 1 */
  666.         if (!WriteBufferedUnsignedChar(Output,1))
  667.             {
  668.                 return eFileLoadDiskError;
  669.             }
  670.  
  671.         /*   2-byte little endian window x location (origin at top-left of screen) */
  672.         /* note that the way we are doing it here, if the window is open, the most */
  673.         /* recent changes to the location will not used. */
  674.         if (!WriteBufferedSignedShortLittleEndian(Output,FuncObj->SavedWindowXLoc))
  675.             {
  676.                 return eFileLoadDiskError;
  677.             }
  678.  
  679.         /*   2-byte little endian window y location */
  680.         if (!WriteBufferedSignedShortLittleEndian(Output,FuncObj->SavedWindowYLoc))
  681.             {
  682.                 return eFileLoadDiskError;
  683.             }
  684.  
  685.         /*   2-byte little endian window width */
  686.         if (!WriteBufferedSignedShortLittleEndian(Output,FuncObj->SavedWindowWidth))
  687.             {
  688.                 return eFileLoadDiskError;
  689.             }
  690.  
  691.         /*   2-byte little endian window height */
  692.         if (!WriteBufferedSignedShortLittleEndian(Output,FuncObj->SavedWindowHeight))
  693.             {
  694.                 return eFileLoadDiskError;
  695.             }
  696.  
  697.         /*   4-byte little endian object name length */
  698.         StringTemp = FunctionObjectGetNameCopy(FuncObj);
  699.         if (StringTemp == NIL)
  700.             {
  701.                 return eFileLoadOutOfMemory;
  702.             }
  703.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  704.             {
  705.                 ReleasePtr(StringTemp);
  706.                 return eFileLoadDiskError;
  707.             }
  708.  
  709.         /*   n-byte name data (line feed = 0x0a) */
  710.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  711.             {
  712.                 ReleasePtr(StringTemp);
  713.                 return eFileLoadDiskError;
  714.             }
  715.         ReleasePtr(StringTemp);
  716.  
  717.         /*   4-byte little endian function source text length */
  718.         StringTemp = FunctionObjectGetSourceCopy(FuncObj);
  719.         if (StringTemp == NIL)
  720.             {
  721.                 return eFileLoadOutOfMemory;
  722.             }
  723.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  724.             {
  725.                 ReleasePtr(StringTemp);
  726.                 return eFileLoadDiskError;
  727.             }
  728.  
  729.         /*   n-byte function source text data (line feed = 0x0a) */
  730.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  731.             {
  732.                 ReleasePtr(StringTemp);
  733.                 return eFileLoadDiskError;
  734.             }
  735.         ReleasePtr(StringTemp);
  736.  
  737.         return eFileLoadNoError;
  738.     }
  739.  
  740.  
  741. /* mark all items in the function object as not changed */
  742. void                                FunctionObjectMarkAsSaved(FunctionObjectRec* FuncObj)
  743.     {
  744.         CheckPtrExistence(FuncObj);
  745.         if (FuncObj->Window != NIL)
  746.             {
  747.                 FunctionWindowWritebackModifiedData(FuncObj->Window);
  748.             }
  749.         FuncObj->Modified = False;
  750.     }
  751.